public interface ExportStrategy {
    void init(OutputStream out, List<String> headers) throws IOException;
    void writeRow(Map<String, Object> rowData) throws IOException;
    void flush() throws IOException;
    void finish() throws IOException;
}

// Excel实现（使用Apache POI流式API）
@Component
@RequiredArgsConstructor
public class ExcelExportStrategy implements ExportStrategy {

    private SXSSFWorkbook workbook;
    private SXSSFSheet sheet;
    private int rowNum = 0;

    @Override
    public void init(OutputStream out, List<String> headers) {
        workbook = new SXSSFWorkbook(100); // 保留100行在内存
        sheet = workbook.createSheet("Records");
        
        // 创建标题行
        Row headerRow = sheet.createRow(rowNum++);
        for (int i = 0; i < headers.size(); i++) {
            headerRow.createCell(i).setCellValue(headers.get(i));
        }
    }

    @Override
    public void writeRow(Map<String, Object> rowData) {
        Row row = sheet.createRow(rowNum++);
        int cellNum = 0;
        for (Object value : rowData.values()) {
            Cell cell = row.createCell(cellNum++);
            if (value instanceof Number) {
                cell.setCellValue(((Number) value).doubleValue());
            } else {
                cell.setCellValue(value.toString());
            }
        }
    }

    @Override
    public void finish() throws IOException {
        workbook.write(out);
        workbook.dispose();
    }
}

// CSV实现
@Component
public class CsvExportStrategy implements ExportStrategy {

    private CSVPrinter csvPrinter;

    @Override
    public void init(OutputStream out, List<String> headers) {
        csvPrinter = new CSVPrinter(new OutputStreamWriter(out), CSVFormat.DEFAULT
                .withHeader(headers.toArray(new String[0])));
    }

    @Override
    public void writeRow(Map<String, Object> rowData) {
        csvPrinter.printRecord(rowData.values());
    }

    @Override
    public void finish() {
        csvPrinter.flush();
    }
}